/* ws2812b_gpio.c */

#include "ws2812b_gpio.h"
#include "hal_gpio.h"

/*
* 在本组件中使用了软件延时的方式实现对WS2812B的操作时序，这在支持多编译器时会遇到兼容性问题，因为不同编译器对代码的优化方式不同，
* 最终将导致最终代码执行时间不同。
* 在本例中，同时支持keil和armgcc两种编译器，在debug模式下，armgcc编译出代码的执行效率相当于kail的一半，因此用于延时的语句数目也
* 要少一半。
*/

void WS2812B_Init(void)
{
    /* 初始化引脚 */
    BSP_InitWs2812bGpio();
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false); /* 低电平 */
    GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT , BSP_GPIO_WS2812B_LEFT_PIN , false); /* 低电平 */
    GPIO_SetPinDir(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true); /* 输出 */
    GPIO_SetPinDir(BSP_GPIO_WS2812B_LEFT_PORT , BSP_GPIO_WS2812B_LEFT_PIN , true); /* 输出 */
}

void WS2812B_ResetRight(void)
{
    uint32_t i;
    for(i = 0U; i< WS2812B_RESET_COUNT; i++)
    {
        GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);        
    }    
}

void WS2812B_ResetLeft(void)
{
    uint32_t i;
    for(i = 0U; i< WS2812B_RESET_COUNT; i++)
    {
        GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);        
    }    
}

void WS2812B_DoUpdateColorRight(uint32_t color)
{
    uint32_t i, ledCount;
    
    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
#if (defined(__GNUC__) && defined(DEBUG))
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
#else
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
#endif
        }
    }
}

void WS2812B_DoUpdateColorLeft(uint32_t color)
{
    uint32_t i, ledCount;

    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
#if (defined(__GNUC__) && defined(DEBUG))
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
#else
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
#endif
        }
    }
}

void WS2812B_DoUpdateColorRightOneByOne(uint32_t led1_color, uint32_t led2_color, uint32_t led3_color)
{
    uint32_t i, ledCount;
	uint32_t color_buf[3], color;

	color_buf[0] = led1_color;
	color_buf[1] = led2_color;
	color_buf[2] = led3_color;

    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
		color = color_buf[ledCount];    
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
#if (defined(__GNUC__) && defined(DEBUG))
            if (0U == (color[ledCount] & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
#else
            if (0U == (color & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_RIGHT_PORT, BSP_GPIO_WS2812B_RIGHT_PIN, false);
            }
#endif
        }
    }
}

void WS2812B_DoUpdateColorLeftOneByOne(uint32_t led1_color, uint32_t led2_color, uint32_t led3_color)
{
    uint32_t i, ledCount;
	uint32_t color[3];

	color[0] = led1_color;
	color[1] = led2_color;
	color[2] = led3_color;

    for (ledCount = 0U; ledCount < BSP_WS2812B_LED_COUNT; ledCount++)
    {
        for (i = 0U; i < WS2812B_DATA_BIT_COUNT_MAX; i++)
        {
#if (defined(__GNUC__) && defined(DEBUG))
            if (0U == (color[ledCount] & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
#else
            if (0U == (color[ledCount] & (1U << (WS2812B_DATA_BIT_COUNT_MAX-1U - i)))) /* bit value = 0. */
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
            else
            {
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, true);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
                GPIO_SetPinLogic(BSP_GPIO_WS2812B_LEFT_PORT, BSP_GPIO_WS2812B_LEFT_PIN, false);
            }
#endif
        }
    }
}



